/****************************************************************************
* MINILOGO - Minimalistic Logo Interpreter
* Copyright (C) 1999-2008 Willian Mitsuda
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* 
*****************************************************************************

*****************************************************************************
* GRWINDOW.C                                                                *
*****************************************************************************
* Funcoes de acesso e interacao com a janela grafica do MINI-LOGO           *
****************************************************************************/
#include <math.h>    // Funcoes matematicas
#include <grx20.h>   // Funcoes graficas
#include "defines.h" // Definicoes do projeto

/****************************************************************************
* void clgr(void)                                                           *
*****************************************************************************
* Limpa a janela grafica                                                    *
****************************************************************************/
void clgr(void)
{
  // Desenha uma caixa preenchida com GBG, nas coordenadas
  // (MINGX, MINGY) ate (MAXGX, MAXGY)...
  GrFilledBox(MINGX, MINGY, MAXGX, MAXGY, GBG);
}

/****************************************************************************
* int round(float v)                                                        *
*****************************************************************************
* Arredonda um valor float                                                  *
*****************************************************************************
* Parametros:                                                               *
*   float v - Valor a ser arredondado                                       *
*****************************************************************************
* Retorna:                                                                  *
*   O valor arredondado                                                     *
****************************************************************************/
// TODO: remover?
/*int round(float v)
{
  // Se a parte decimal for menor que .5, arredonda p/ baixo...
  // ... caso contrario, para cima...
  v += .5;
  return(floor(v));
}*/

/****************************************************************************
* int transX(float *x)                                                      *
*****************************************************************************
* Reposiciona a coordenada X da tartaruga                                   *
*****************************************************************************
* Parametros:                                                               *
*   float *x - Endereco de uma variavel float cujo valor eh uma coordenada  *
* x que sera reposicionada para dentro da tela                              *
*****************************************************************************
* Retorna:                                                                  *
*   O numero de "movimentacoes" que foi feito                               *
****************************************************************************/
int transX(float *x)
{
  int k = 0;

  while(round(*x) < GXMIN)
  {
    *x += GXLEN;
    k++;
  }
  while(round(*x) > GXMAX)
  {
    *x -= GXLEN;
    k--;
  }
  return(k);
}

/****************************************************************************
* int transY(float *y)                                                      *
*****************************************************************************
* Reposiciona a coordenada Y da tartaruga                                   *
*****************************************************************************
* Parametros:                                                               *
*   float *y - Endereco de uma variavel float cujo valor eh uma coordenada  *
* y que sera reposicionada para dentro da tela                              *
*****************************************************************************
* Retorna:                                                                  *
*   O numero de "movimentacoes" que foi feito                               *
****************************************************************************/
int transY(float *y)
{
  int k = 0;

  while(round(*y) < GYMIN)
  {
    *y += GYLEN;
    k++;
  }
  while(round(*y) > GYMAX)
  {
    *y -= GYLEN;
    k--;
  }
  return(k);
}

/****************************************************************************
* void line(float x1, float y1, float x2, float y2, GrColor cor)            *
*****************************************************************************
* Desenha uma linha quebrando-a se necessario                               *
*****************************************************************************
* Parametros:                                                               *
*   float x1, y1 - Coordenadas (x, y) do ponto inicial                      *
*   float x2, y2 - Coordenadas (x, y) do ponto final                        *
*   GrColor cor  - Cor da linha                                             *
****************************************************************************/
void line(float x1, float y1, float x2, float y2, GrColor cor)
{
  float x1q, y1q, x2q, y2q;
  int quebrou, k;
  float da, db, dc;

  do
  {
    quebrou = 0;

    // Posiciona x2, y2 dentro da janela grafica...
    k = transX(&x2);
    x1 += k * GXLEN;

    k = transY(&y2);
    y1 += k * GYLEN;

    // Quebra o excesso...
    da = y1 - y2;
    db = x2 - x1;
    dc = x2 * y1 - x1 * y2;
    x1q = x1;
    y1q = y1;
    if(round(x1) < GXMIN)
    {
      x2q = GXMIN - 1;
      y2q = (dc - x2q * da) / db;
      x1 = GXMIN;
      y1 = (dc - x1 * da) / db;
      quebrou = 1;
    }
    if(round(x1) > GXMAX)
    {
      x2q = GXMAX + 1;
      y2q = (dc - x2q * da) / db;
      x1 = GXMAX;
      y1 = (dc - x1 * da) / db;
      quebrou = 1;
    }
    if(round(y1) < GYMIN)
    {
      y2q = GYMIN - 1;
      x2q = (dc - y2q * db) / da;
      y1 = GYMIN;
      x1 = (dc - y1 * db) / da;
      quebrou = 1;
    }
    if(round(y1) > GYMAX)
    {
      y2q = GYMAX + 1;
      x2q = (dc - y2q * db) / da;
      y1 = GYMAX;
      x1 = (dc - y1 * db) / da;
      quebrou = 1;
    }

    // Desenha a linha resultante...
    GrLine(round(GX0 + x1), round(GY0 - y1),
           round(GX0 + x2), round(GY0 - y2), cor);

    // Desenha a linha restante...
    if(quebrou)
    {
      x1 = x1q;
      y1 = y1q;
      x2 = x2q;
      y2 = y2q;
    }
  } while(quebrou);
}
